package Ontology;
        
import java.sql.*;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Map;

import topindex.Index;
import wikipedia.util.Encodings;

public class WebDESOOntology
{
	/**
	 * @param args
	 */
	static public int iOntoID, iLangID;		//	Ontology ID and language ID. 0 - English (DESFA), 1 - Russian
	//	List of variable to work with database
	static private Connection cnDBConnection;
	static private Statement stDBStatement;
	static private Statement stDBDeso;
	static private PreparedStatement 
            pstSetCharSet,
			pstClass, 
			pstAttr, 
			pstClassAttr, 
			pstAcon, 
			pstCompatible, 
			pstHierarchy, 
			pstClassesByClass, 
			pstAttrByClass,
			pstWDFunc,
			pstValuesOfTextAttributes; 
	static private ResultSet rsDB;
	static private String SQL_PREPARED_SELECT_STATEMENT_CLASS = "SELECT class.id, onto_id, parent_id, term_id, lang_id, text, description, stem_text, stem_description, 0 AS leaf, base_onto_id FROM class LEFT JOIN term ON ( term.id = term_id AND lang_id = ? ) WHERE class.id IN ( SELECT parent_id FROM class class1 ) AND onto_id = ? " + 
			" UNION ALL " +
			"SELECT class.id, onto_id, parent_id, term_id, lang_id, text, description, stem_text, stem_description, 1 AS leaf, base_onto_id FROM class LEFT JOIN term ON ( term.id = term_id AND lang_id = ? ) WHERE class.id NOT IN ( SELECT parent_id FROM class class1 ) AND onto_id = ? ";	//	 	ORDER BY 1
	static private String SQL_PREPARED_SELECT_STATEMENT_ATTR = "SELECT attr.id, onto_id, term_id, lang_id, text, type, description, stem_text, stem_description FROM attr LEFT JOIN term ON ( term.id = term_id AND lang_id = ? ) WHERE onto_id = ?";
	static private String SQL_PREPARED_SELECT_STATEMENT_CLASS_ATTR = "SELECT class_id, attr_id, domtype_id, min, max, limited FROM class_attr WHERE class_id IN ( SELECT id From class WHERE onto_id = ? ) AND attr_id IN ( SELECT id From attr WHERE onto_id = ? )";
	static private String SQL_PREPARED_SELECT_STATEMENT_COMPATIBLE = "SELECT class1_id, class2_id, is_compatible, id FROM compatible WHERE onto_id = ?";	//	 	ORDER BY 1
	static private String SQL_PREPARED_SELECT_STATEMENT_HIERARCHY = "SELECT parent_class_id, child_class_id, card_min, card_max, ID  FROM hierarchy WHERE onto_id = ?";
	static private String SQL_PREPARED_SELECT_STATEMENT_ACON = "SELECT class1_id, class2_id, id FROM acon WHERE onto_id = ?";
	static private String SQL_PREPARED_SELECT_STATEMENT_ATTR_BY_CLASS = "SELECT * FROM class_attr WHERE onto_id = ?";

	static private String SQL_PREPARED_SELECT_STATEMENT_CLASSES_BY_CLASS = "SELECT id FROM class WHERE onto_id = ? AND parent_id = ?";
	static private String SQL_PREPARED_SELECT_STATEMENT_WDFunc = "SELECT term_id AS termid, attrout_id AS attroutid, relation_type AS relationtype, relation_id AS relationid, func_type AS functype, func_value AS funcvalue, sign, id AS idfromdb FROM func_constr WHERE func_type = 0 AND  relation_type = 0 AND  attrout_id IN ( SELECT id From attr WHERE onto_id = ? )";
	
    static private String SQL_PREPARED_SELECT_STATEMENT_VALUES_OF_TEXT_ATTRIBUTES = "SELECT class.id AS classid, attr.id AS attrid, class_attr_id AS classattrid, collectionitem AS attrvalue, stem_collectionitem AS stemattrvalue, domtype_collection.id FROM domtype_collection, class_attr, class, attr WHERE class_attr_id = class_attr.id AND class.id = class_id AND attr.id = attr_id AND class.onto_id = ? AND attr.onto_id = ? and Lang_ID = ?";
    
    static private String SQL_CHARSET = "SET CHARACTER SET latin1";
    
	public static Hashtable htClasses, htAttributes;
	public static Vector vClassAttr, vClasses, vAttributes, vWDHier, vWDAssoc, vWDFunc, vWDTax, vWDTextAttrValues, vWDComp;
	public static int iThingID;
	static private int iCountAssoc = 0;
	
	/*
	 * iiOntoID - identifier of the ontology to be extracted
	 */
    /**
     * @deprecated iLangID is required
     */
	public WebDESOOntology( int iiOntoID ) 
	{
		//	System.out.println( "Begin WDO!" );

		iLangID = 0;
        initVars( iiOntoID, Index.WEBDESO_HOST, Index.WEBDESO_USER, Index.WEBDESO_PASS);
         //	System.out.println( "End WDO!" );
	}

	/*
	 * iiOntoID - identifier of the ontology to be extracted
	 * iiLangID - languageID
	 */
        public WebDESOOntology( int iiOntoID, int iiLangID ) 
	{//	System.out.println( "Begin WDO!" );
            iLangID = iiLangID;
            initVars( iiOntoID, Index.WEBDESO_HOST, Index.WEBDESO_USER, Index.WEBDESO_PASS);
            // System.out.println( "End WDO!" );
	}

	//	a set of database functions - BEGIN
	static int estDatabaseConnect( String isDatabaseName, String isLogin, String isPassword )
	{
		try 
	    {
			cnDBConnection = getConnection( isDatabaseName, isLogin, isPassword );
	    }
	    catch ( Exception e ) 
	    {
	        e.printStackTrace( );
	    	return -1;
	    }
	    if ( cnDBConnection  == null ) return -1;	// mistake, can not get connection

		// Statement of the database
		try 
	    {
            pstSetCharSet = getPreparedStatement( cnDBConnection, SQL_CHARSET);
			pstClass = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_CLASS );
			pstAttr = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_ATTR );
			pstClassAttr = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_CLASS_ATTR );
			pstAcon = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_ACON );
			pstCompatible = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_COMPATIBLE );
			pstHierarchy = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_HIERARCHY );
			pstClassesByClass = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_CLASSES_BY_CLASS );
			pstAttrByClass = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_ATTR_BY_CLASS );
			pstWDFunc = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_WDFunc );
			pstValuesOfTextAttributes = getPreparedStatement( cnDBConnection, SQL_PREPARED_SELECT_STATEMENT_VALUES_OF_TEXT_ATTRIBUTES );
	    }
	    catch ( Exception e ) 
	    {
	        e.printStackTrace( );
	        closeAll();
	        return -1;
	    }
		if ( 
				( pstClass == null ) 
				|| ( pstAttr == null ) 
				|| ( pstClassAttr == null )
				|| ( pstAcon == null )
				|| ( pstCompatible == null )
				|| ( pstHierarchy == null )
				|| ( pstClassesByClass == null )
				|| ( pstAttrByClass == null )
				|| ( pstWDFunc == null )
				|| ( pstValuesOfTextAttributes == null )
			)	 
		{
			closeAll();
			return -1;
		}
		return 0;
	}
	
	public static Connection getConnection( String isDatabaseName, String isLogin, String isPassword ) throws Exception 
	{
		Driver d = (Driver)Class.forName( "com.mysql.jdbc.Driver" ).newInstance();
        Connection c = DriverManager.getConnection( "jdbc:mysql://" + isDatabaseName, isLogin, isPassword );	//	&autoReconnect=true&useUnbufferedInput=false
		return c;
    }
	
	static PreparedStatement getPreparedStatement( Connection iconnConn, String isSQL ) throws Exception
	{
		PreparedStatement pstmnt;
		
		pstmnt = iconnConn.prepareStatement
				(
					isSQL,
					//ResultSet.TYPE_SCROLL_SENSITIVE,
					ResultSet.TYPE_FORWARD_ONLY,
					ResultSet.CONCUR_UPDATABLE
				);
		return pstmnt;
	}

	static void closeAll()
	{
		try
		{ 
			if ( cnDBConnection != null )cnDBConnection.close();
			if ( pstClass != null ) pstClass.close();
			if ( pstAttr != null ) pstAttr.close();
			if ( pstClassAttr != null ) pstClassAttr.close();
			if ( pstAcon != null ) pstAcon.close();
			if ( pstCompatible != null ) pstCompatible.close();
			if ( pstHierarchy != null ) pstHierarchy.close();
			if ( pstClassesByClass != null ) pstClassesByClass.close();
			if ( pstAttrByClass != null ) pstAttrByClass.close();
			if ( pstWDFunc != null ) pstWDFunc.close();
			if ( pstValuesOfTextAttributes != null ) pstValuesOfTextAttributes.close();
		}
	    catch ( Exception e ) 
	    {
	    }
	    return;
	} 		//	CloseAll()
	//	a set of database functions - END
	
	static void initVars( int iiOntoID, String isDatabaseName, String isLogin, String isPassword )
	{
		iOntoID = iiOntoID;
		
		if ( estDatabaseConnect( isDatabaseName, isLogin, isPassword ) == -1 ) return;
		//	System.out.println( "Connection is OK" );
		
		initClasses();
		initAttributes();
		initClassAttr();		//	read relations class_attr, associative, hierarchy, compatibility, functional (the code is similar)
		initValuesOfTextAttributes();
	    
		closeAll();
		//	System.out.println( "Bye!" );
		
	}		//	initVars
	
                                                                            
	static void initClasses()
	{
		String sText, sDescr, sStemText, sStemDescr;	// to store class name and description
		int iClassID;	//	to store class ID
		byte[] b;
		Classes clTemp;
		
		//	System.out.println( "initClasses begin..." );
		
		htClasses = null;
		htClasses = new Hashtable();
		vClasses = null;
		vClasses = new Vector();
		vWDTax = null;
		vWDTax = new Vector();
		vWDTextAttrValues = null;
		vWDTextAttrValues = new Vector();

		boolean bDelIt = true;
		int iDelIt = 0;
        
		try
		{
            pstSetCharSet.executeQuery();
            
			pstClass.setInt( 1, iLangID );
			pstClass.setInt( 2, iOntoID );
			pstClass.setInt( 3, iLangID );
			pstClass.setInt( 4, iOntoID );
			rsDB = pstClass.executeQuery();
			if ( rsDB.next() )
			{
				//	System.out.println( "Classes:" );
				do
				{
					
                    
                    b = null;
                    
                    b = rsDB.getBytes("Text");
                    sText = null == b ? "" : Encodings.bytesTo(b, "UTF8");
                    
                    b = rsDB.getBytes("Description");
                    sDescr = null == b ? "" : Encodings.bytesTo(b, "UTF8");
                    
                    b = rsDB.getBytes("Stem_Text");
                    sStemText = null == b ? "" : Encodings.bytesTo(b, "UTF8");
					
                    b = rsDB.getBytes("Stem_Description");
                    sStemDescr = null == b ? "" : Encodings.bytesTo(b, "UTF8");
					
					
					//	System.out.println( "ID: " + rsDB.getInt( "Id" ) + " OntoID: " + rsDB.getInt( "Onto_id" ) + " ParentID: " + rsDB.getInt( "Parent_id" ) + " TermID: " + rsDB.getInt( "Term_id" ) + " LangID: " + rsDB.getInt( "lang_id" ) + " Text: " + sText );
					iClassID = rsDB.getInt( "Id" );
					clTemp = null;
					clTemp = new Classes( iClassID, sText, rsDB.getInt( "Parent_id" ), rsDB.getInt( "Leaf" ) == 0 ? false : true, sDescr, sStemText, sStemDescr, rsDB.getInt( "Base_Onto_id" ) );
					htClasses.put( new Integer( iClassID ), clTemp );	//	new Object(
					vClasses.add( new Integer( iClassID ) );
					if ( clTemp.getParentID() == 0 ) iThingID = clTemp.getClassID(); 
					vWDTax.add( new WDTax( rsDB.getInt( "Parent_id" ), iClassID ) );
				} while( rsDB.next() );
			}
			else
			{
				System.out.println( "Classes not found..." );
			}
			rsDB = null;
			//	GET CLASSES - END		
		}
	    catch ( Exception e ) 
	    {
	    	e.printStackTrace( );
	    	return;
	    }
	    
	    //	System.out.println( "initClasses end!" );
	    
	}		//	initClasses

	static void initAttributes()
	{
		String sText, sDescr, sStemText, sStemDescr;	// to store attribute name and description
		int iAttrID;	//	to store ttribute ID
		Attributes attrTemp;
		byte[] b;

		//	System.out.println( "initAttributes begin..." );
		
		htAttributes = null;
		htAttributes = new Hashtable();
		vAttributes = null;
		vAttributes = new Vector();

		try
		{
			//	pstAttr.setInt( 1, iOntoID );
			pstAttr.setInt( 1, iLangID );
			pstAttr.setInt( 2, iOntoID );
			rsDB = pstAttr.executeQuery();
			if ( rsDB.next() )
			{
				//	System.out.println( "Attributes:" );
				do
				{
                    
                    b = null;
                    
                    b = rsDB.getBytes("Text");
                    sText = null == b ? "" : Encodings.bytesTo(b, "UTF8");
                    
                    b = rsDB.getBytes("Description");
                    sDescr = null == b ? "" : Encodings.bytesTo(b, "UTF8");
                    
                    b = rsDB.getBytes("Stem_Text");
                    sStemText = null == b ? "" : Encodings.bytesTo(b, "UTF8");
					
                    b = rsDB.getBytes("Stem_Description");
                    sStemDescr = null == b ? "" : Encodings.bytesTo(b, "UTF8");
					
					//	System.out.println( "ID: " + rsDB.getInt( "Id" ) + " OntoID: " + rsDB.getInt( "Onto_id" ) + " Type: " + rsDB.getInt( "Type" ) + " TermID: " + rsDB.getInt( "Term_id" ) + " LangID: " + rsDB.getInt( "Lang_id" ) + " Text: " + sText );
					iAttrID = rsDB.getInt( "Id" );
					attrTemp = null;
					attrTemp = new Attributes( iAttrID, sText, rsDB.getInt( "Type" ), sDescr, sStemText, sStemDescr );
					//	System.out.println( attrTemp.toString() );
					htAttributes.put( new Integer( iAttrID ), attrTemp );
					vAttributes.add( new Integer( iAttrID ) );
				} while( rsDB.next() );
			}
			else
			{
				System.out.println( "Attributes not found..." );
			}
			rsDB = null;
		}
	    catch ( Exception e ) 
	    {
	    	e.printStackTrace( );
	    	return;
	    }
	    
	    //	System.out.println( "initAttributes end!" );
	    
	}		//	initAttributes
	
	static void initClassAttr()
	{
		int iAttrID;	//	to store attribute ID
		int iClassID, iChildClassID;	//	to store Father ID
		//	************************
		long lStartTime = System.currentTimeMillis();
		//	System.out.println( "initClassAttr/Hier/Assoc begin..." );
		
		ClassAttr clattrTemp;
		Vector vQueue;

		vClassAttr = null;
		vClassAttr = new Vector();
		
		vQueue = new Vector();
		vQueue.add( new Integer ( 0 ));
		
		ResultSet rsAttrByClass;
		
		vWDHier = null;
		vWDHier = new Vector();
		
		WDHier wdhTemp;
		
		vWDAssoc = null;
		vWDAssoc = new Vector();
		
		WDAssoc wdaTemp;

		vWDComp = null;
		vWDComp = new Vector();
		
		WDComp wdcTemp, wdcTemp1;

		WDFunc wdfTemp;
		
		vWDFunc = null;
		vWDFunc = new Vector();

		Vector vClassAttrAux, vWDAssocAux, vWDHierAux, vWDCompAux, vWDFuncAux;
		vClassAttrAux = new Vector();
		vWDAssocAux = new Vector();
		vWDHierAux = new Vector();
		vWDCompAux = new Vector();
		vWDFuncAux = new Vector();
		
		WDAssoc wdaTemp1;

		//	Read the tables first. Fill out auxiliary structures 
		try
		{
			//	Class_id, Attr_id, Domtype_id, Min, Max, Limited
			pstClassAttr.setInt( 1, iOntoID );
			pstClassAttr.setInt( 2, iOntoID );
			rsAttrByClass = pstClassAttr.executeQuery();
			if ( rsAttrByClass.next() )
			{
				do
				{
					clattrTemp = null;
					clattrTemp = new ClassAttr( rsAttrByClass.getInt( "Class_ID" ), rsAttrByClass.getInt( "Attr_ID" ), false, rsAttrByClass.getInt( "Class_ID" ) );
					vClassAttrAux.add( clattrTemp );
					
				} while( rsAttrByClass.next() );
			}
			rsAttrByClass = null;

			pstHierarchy.setInt( 1, iOntoID );
			rsAttrByClass = pstHierarchy.executeQuery();
			if ( rsAttrByClass.next() )
			{
				do
				{
					wdhTemp = null;
					wdhTemp = new WDHier( rsAttrByClass.getInt( "Parent_class_id" ), 
							rsAttrByClass.getInt( "Child_class_id" ), 
							false, 
							rsAttrByClass.getInt( "Parent_class_id" ), 
							rsAttrByClass.getInt( "Card_min" ), 
							rsAttrByClass.getInt( "Card_max" ), 
							rsAttrByClass.getInt( "ID" )
							);
					vWDHierAux.add( wdhTemp );
				} while( rsAttrByClass.next() );
			}

			pstAcon.setInt( 1, iOntoID );

			rsAttrByClass = pstAcon.executeQuery();
			if ( rsAttrByClass.next() )
			{
				do
				{
					wdaTemp = null;
					wdaTemp = new WDAssoc( 
							rsAttrByClass.getInt( "Class1_ID" ), 
							rsAttrByClass.getInt( "Class2_ID" ), 
							false, 
							rsAttrByClass.getInt( "Class1_ID" ),
							rsAttrByClass.getInt( "ID" ),
							iCountAssoc++
							);
					vWDAssocAux.add( wdaTemp );
				} while( rsAttrByClass.next() );
			}	

			pstCompatible.setInt( 1, iOntoID );

			rsAttrByClass = pstCompatible.executeQuery();
			if ( rsAttrByClass.next() )
			{
				do
				{
					wdcTemp = null;
					wdcTemp = new WDComp( 
							rsAttrByClass.getInt( "Class1_ID" ), 
							rsAttrByClass.getInt( "Class2_ID" ), 
							false, 
							rsAttrByClass.getInt( "Class1_ID" ),
							rsAttrByClass.getInt( "ID" ),
							rsAttrByClass.getInt( "Is_Compatible" )
							);
					vWDCompAux.add( wdcTemp );
				} while( rsAttrByClass.next() );
			}	

			pstWDFunc.setInt( 1, iOntoID );		

			rsAttrByClass = pstWDFunc.executeQuery();
				
			if ( rsAttrByClass.next() )
			{
				do
				{
					wdfTemp = null;
					//	TermID, AttrOutID, RelationType, RelationID, FuncType, FuncValue, Sign, IDFromDB
					wdfTemp = new WDFunc(
							rsAttrByClass.getInt("TermID"),
							rsAttrByClass.getInt("AttrOutID"),
							rsAttrByClass.getInt("RelationType"),
							rsAttrByClass.getInt("RelationID"),
							rsAttrByClass.getInt("FuncType"),
							rsAttrByClass.getInt("FuncValue"),
							rsAttrByClass.getInt("Sign"),
							rsAttrByClass.getInt("IDFromDB"),
							0,
							false,
							rsAttrByClass.getInt("RelationID")
							);
							
							//	iRelID, iRelType, iCondType==0?true:false,iArrLength, iAttrCondID1, iAttrCondID2 , iCondID);
					vWDFuncAux.add( wdfTemp );
				} while( rsAttrByClass.next() );
			}	//	if next

		}
	    catch ( Exception e ) 
	    {
	    	e.printStackTrace( );
	    	return;
	    }

		
		do 
		{
			iClassID = Integer.parseInt( vQueue.elementAt( 0 ).toString() );	//	Get father class ID
			for ( int iLoopByClasses = 0; iLoopByClasses < vWDTax.size(); iLoopByClasses++ )
			{
				if ( ( ( WDTax ) vWDTax.elementAt( iLoopByClasses ) ).getParentID() == iClassID )
				{
					iChildClassID = ( ( WDTax ) vWDTax.elementAt( iLoopByClasses ) ).getChildID();
					vQueue.add( new Integer ( iChildClassID ));
						
					//	Attributes
						
					boolean bWasFoundAttribute = false;

					//	Get new attributes!
					for ( int iNewAttr = 0 ; iNewAttr < vClassAttrAux.size(); iNewAttr++ )
					{
						clattrTemp = ( ClassAttr ) vClassAttrAux.elementAt( iNewAttr );
						if ( clattrTemp.getClassID() == iChildClassID )
						{
							vClassAttr.add( clattrTemp );
							if ( !bWasFoundAttribute )
							{
								updateClassAttrPos( iChildClassID, vClassAttr.size() );
								bWasFoundAttribute = true;
							};
						}	//	get attributes
					}		//	search in the auxiliary structure
						
					//	Get inherited  attributes!
					boolean bWasFound = false;
					ClassAttr clattrTemp1;
					for ( int i = 0; i < vClassAttr.size(); i++ )
					{
						clattrTemp1 = ( ClassAttr )vClassAttr.elementAt( i );
						
						if ( clattrTemp1.getClassID() == iClassID )	// found father's attribute
						{
							bWasFound = true;
							clattrTemp = new ClassAttr( iChildClassID, clattrTemp1.getAttrID(), true, clattrTemp1.getFatherClassID() );
							
							vClassAttr.add( clattrTemp );
							if ( !bWasFoundAttribute )
							{
								updateClassAttrPos( iChildClassID, vClassAttr.size() );
								bWasFoundAttribute = true;
							};
						}
						else
						{
							if ( bWasFound )	//	finish a loop
							{
								i = vClassAttr.size() + 1;
							}
						};
					};  			// End of attributes
						
					//	**************************************************************
					
					//	Hierarchy
					
					//	Get new part-of relations!
					for ( int iNewHier = 0 ; iNewHier < vWDHierAux.size(); iNewHier++ )
					{
						wdhTemp = ( WDHier ) vWDHierAux.elementAt( iNewHier );
						if ( wdhTemp.getClass1ID() == iChildClassID )
						{
							vWDHier.add( wdhTemp );
						}	//	get hierarchical relations
					}		//	search in the auxiliary structure
					
					//	Get inherited  relations!
					bWasFound = false;
					WDHier wdhTemp1;
					for ( int i = 0; i < vWDHier.size(); i++ )
					{
						wdhTemp1 = ( WDHier )vWDHier.elementAt( i );
						
						if ( wdhTemp1.getClass1ID() == iClassID )	// found father's hierarchical relation
						{
							bWasFound = true;
							wdhTemp = new WDHier( iChildClassID, wdhTemp1.getClass2ID(), true, wdhTemp1.getFatherClassID(), wdhTemp1.getCardMin(), wdhTemp1.getCardMax(), wdhTemp1.getIDFromDB() );
							
							vWDHier.add( wdhTemp );
						}
						else
						{
							if ( bWasFound )	//	finish a loop
							{
								i = vWDHier.size() + 1;
							}
						};
					};
					//	End of hierarchy
					
					//	**************************************************************

					//	Associative
					wdaTemp = null;

					//	Get new associative relations
					for ( int iNewAssoc = 0 ; iNewAssoc < vWDAssocAux.size(); iNewAssoc++ )
					{
						wdaTemp1 = ( WDAssoc ) vWDAssocAux.elementAt( iNewAssoc );
						wdaTemp = new WDAssoc( wdaTemp1.getClass1ID(), 
								wdaTemp1.getClass2ID(), 
								false, 
								wdaTemp1.getFatherClassID(), 
								wdaTemp1.getIDFromDB(),
								iCountAssoc++
								);
						//	Associative left -> right
						if ( wdaTemp.getClass1ID() == iChildClassID )
						{
							vWDAssoc.add( wdaTemp );
						}	
						//	Associative right -> left
						if ( wdaTemp.getClass2ID() == iChildClassID )
						{
							wdaTemp.setDelIt( true );
							wdaTemp.setLeftRight( false );
							vWDAssoc.add( wdaTemp );
						}	
						wdaTemp = null;
						
					}		//	Get new associative relations

					/*
					//	Get inherited  associative relations
					bWasFound = false;
					for ( int i = 0; i < vWDAssoc.size(); i++ )
					{
						wdaTemp1 = ( WDAssoc )vWDAssoc.elementAt( i );
						
						//	Associative left -> right  
						if ( wdaTemp1.getClass1ID() == iClassID && wdaTemp1.getLeftRight() )	// found father's hierarchical relation
						{
							bWasFound = true;
							wdaTemp = new WDAssoc( iChildClassID, 
									wdaTemp1.getClass2ID(), 
									true, 
									wdaTemp1.getFatherClassID(), 
									wdaTemp1.getIDFromDB(),
									iCountAssoc++
									);
							vWDAssoc.add( wdaTemp );
						}
						else
						{
							//	Associative right -> left 
							if ( wdaTemp1.getClass2ID() == iClassID && !wdaTemp1.getLeftRight())	// found father's hierarchical relation
							{
								bWasFound = true;
								wdaTemp = new WDAssoc( wdaTemp1.getClass1ID(), 
										iChildClassID, 
										true, 
										wdaTemp1.getFatherClassID(), 
										wdaTemp1.getIDFromDB(),
										iCountAssoc++
										);
								wdaTemp.setLeftRight( false );
								vWDAssoc.add( wdaTemp );
							}
							//if ( bWasFound )	//	finish a loop
							//{
							//	i = vWDAssoc.size() + 1;
							//}
						};

					};
					*/

					//	End of Associative

					//	**************************************************************

					//	Compatible

					//	Get new Compatible relations
					for ( int iNewComp = 0 ; iNewComp < vWDCompAux.size(); iNewComp++ )
					{
						wdcTemp1 = ( WDComp ) vWDCompAux.elementAt( iNewComp );
						wdcTemp = new WDComp( wdcTemp1.getClass1ID(), 
								wdcTemp1.getClass2ID(), 
								false, 
								wdcTemp1.getClass1ID(), 
								wdcTemp1.getIDFromDB(),
								wdcTemp1.getIsCompatible()
								);
						//	left->right
						if ( wdcTemp.getClass1ID() == iChildClassID )
						{
							vWDComp.add( wdcTemp );
						}	
//						//	right->left
						if ( wdcTemp.getClass2ID() == iChildClassID )
						{
							wdcTemp.setDelIt( true );
							wdcTemp.setLeftRight( false );
							vWDComp.add( wdcTemp );
						}	
						wdcTemp = null;
					}		//	search in the auxiliary structure
					
					/*
					//	Get inherited  compatibility relations
					bWasFound = false;
					for ( int i = 0; i < vWDComp.size(); i++ )
					{
						wdcTemp1 = ( WDComp )vWDComp.elementAt( i );
						//	left -> right
						if ( wdcTemp1.getClass1ID() == iClassID && wdcTemp1.getLeftRight())	// found father's compatibility relation
						{
							bWasFound = true;
							wdcTemp = new WDComp( iChildClassID, 
									wdcTemp1.getClass2ID(), 
									true, 
									wdcTemp1.getClass1ID(), 
									wdcTemp1.getIDFromDB(),
									wdcTemp1.getIsCompatible()
									);
							vWDComp.add( wdcTemp );
						}
						else
						{
							//	right -> left 
							if ( wdcTemp1.getClass2ID() == iClassID && !wdcTemp1.getLeftRight())	// found father's hierarchical relation
							{
								bWasFound = true;
								wdcTemp = new WDComp( wdcTemp1.getClass1ID(), 
										iChildClassID, 
										true, 
										wdcTemp1.getClass1ID(), 
										wdcTemp1.getIDFromDB(),
										wdcTemp1.getIsCompatible()
										);
								wdcTemp.setLeftRight( false );
								vWDComp.add( wdcTemp );
							}
							//	if ( bWasFound )	//	finish a loop
							//	{
							//	i = vWDComp.size() + 1;
							//}
						};
					};
					*/
					
					//	End of Compatible

					//	**************************************************************
					
					//	Functional
					
					//	Get new functional relations!
					for ( int iNewFunc = 0 ; iNewFunc < vWDFuncAux.size(); iNewFunc++ )
					{
						wdfTemp = ( WDFunc ) vWDFuncAux.elementAt( iNewFunc );
						if ( wdfTemp.getRelationID() == iChildClassID )
						{
							vWDFunc.add( wdfTemp );
						}	//	get hierarchical relations
					}		//	search in the auxiliary structure
					
					//	Get inherited  relations!
					bWasFound = false;
					WDFunc wdfTemp1;
					for ( int i = 0; i < vWDFunc.size(); i++ )
					{
						wdfTemp1 = ( WDFunc )vWDFunc.elementAt( i );
						
						if ( wdfTemp1.getRelationID() == iClassID )	// found father's hierarchical relation
						{
							bWasFound = true;
							wdfTemp = new WDFunc(
									wdfTemp1.getTermID(),
									wdfTemp1.getAttrOutID(),
									wdfTemp1.getRelationType(),
									wdfTemp1.getRelationID(),
									wdfTemp1.getFuncType(),
									wdfTemp1.getFuncValue(),
									wdfTemp1.getSign(),
									wdfTemp1.getIDFromDB(),
									wdfTemp1.getConstrID(),
									true,
									iClassID
									);
							
							vWDFunc.add( wdfTemp );
						}
						else
						{
							if ( bWasFound )	//	finish a loop
							{
								i = vWDFunc.size() + 1;
							}
						};
					};
					//	End of functional constraints

				}								//	Class has subclasses	
			}	//	LOOP BY CLASSES
			vQueue.removeElementAt( 0 );
		} while ( vQueue.size() > 0 );


		//	get inherited! to save order!!! 
		vQueue = new Vector();
		vQueue.add( new Integer ( 0 ));
		do 
		{
			iClassID = Integer.parseInt( vQueue.elementAt( 0 ).toString() );	//	Get father class ID
			for ( int iLoopByClasses = 0; iLoopByClasses < vWDTax.size(); iLoopByClasses++ )
			{
				if ( ( ( WDTax ) vWDTax.elementAt( iLoopByClasses ) ).getParentID() == iClassID )
				{
					iChildClassID = ( ( WDTax ) vWDTax.elementAt( iLoopByClasses ) ).getChildID();
					vQueue.add( new Integer ( iChildClassID ));
					boolean bWasFound;
					
					//	Associative
					wdaTemp = null;
					
					//	Get inherited  associative relations
					bWasFound = false;
					for ( int i = 0; i < vWDAssoc.size(); i++ )
					{
						wdaTemp1 = ( WDAssoc )vWDAssoc.elementAt( i );
						
						//	Associative left -> right  
						if ( wdaTemp1.getClass1ID() == iClassID && wdaTemp1.getLeftRight() )	// found father's hierarchical relation
						{
							bWasFound = true;
							wdaTemp = new WDAssoc( iChildClassID, 
									wdaTemp1.getClass2ID(), 
									true, 
									wdaTemp1.getFatherClassID(), 
									wdaTemp1.getIDFromDB(),
									iCountAssoc++
									);
							vWDAssoc.add( wdaTemp );
						}
						else
						{
							//	Associative right -> left 
							if ( wdaTemp1.getClass2ID() == iClassID && !wdaTemp1.getLeftRight())	// found father's hierarchical relation
							{
								bWasFound = true;
								wdaTemp = new WDAssoc( wdaTemp1.getClass1ID(), 
										iChildClassID, 
										true, 
										wdaTemp1.getFatherClassID(), 
										wdaTemp1.getIDFromDB(),
										iCountAssoc++
										);
								wdaTemp.setLeftRight( false );
								vWDAssoc.add( wdaTemp );
							}
						};

					};	//	END of assoc
					
					//	Compatible
					bWasFound = false;
					for ( int i = 0; i < vWDComp.size(); i++ )
					{
						wdcTemp1 = ( WDComp )vWDComp.elementAt( i );
						//	left -> right
						if ( wdcTemp1.getClass1ID() == iClassID && wdcTemp1.getLeftRight())	// found father's compatibility relation
						{
							bWasFound = true;
							wdcTemp = new WDComp( iChildClassID, 
									wdcTemp1.getClass2ID(), 
									true, 
									wdcTemp1.getClass1ID(), 
									wdcTemp1.getIDFromDB(),
									wdcTemp1.getIsCompatible()
									);
							vWDComp.add( wdcTemp );
						}
						else
						{
							//	right -> left 
							if ( wdcTemp1.getClass2ID() == iClassID && !wdcTemp1.getLeftRight())	// found father's hierarchical relation
							{
								bWasFound = true;
								wdcTemp = new WDComp( wdcTemp1.getClass1ID(), 
										iChildClassID, 
										true, 
										wdcTemp1.getClass1ID(), 
										wdcTemp1.getIDFromDB(),
										wdcTemp1.getIsCompatible()
										);
								wdcTemp.setLeftRight( false );
								vWDComp.add( wdcTemp );
							}
						};
					};
		
				}								//	Class has subclasses	
			}	//	LOOP BY CLASSES
			vQueue.removeElementAt( 0 );
		} while ( vQueue.size() > 0 );
		
		
		for ( int i = 0; i < vWDAssoc.size(); i++ )
		{
			wdaTemp1 = ( WDAssoc )vWDAssoc.elementAt( i );
			if ( wdaTemp1.getDelIt() )
			{
				vWDAssoc.removeElementAt( i );
				i--;
			}
		}
		
		for ( int i = 0; i < vWDComp.size(); i++ )
		{
			wdcTemp1 = ( WDComp )vWDComp.elementAt( i );
			if ( wdcTemp1.getDelIt() )
			{
				vWDComp.removeElementAt( i );
				i--;
			}
		}

		//System.out.println( "Total associative relations: " + vWDAssoc.size() );
		//System.out.println( "Total compatible relations: " + vWDComp.size() );
		//for ( int i = 0; i < vWDAssoc.size(); i++ )
		//{
		////	if ( ( ( WDAssoc )vWDAssoc.elementAt( i ) ).getClass1ID() == 84384 )
		//	System.out.println( ( ( WDAssoc )vWDAssoc.elementAt( i ) ).toFileWithTab());
		//}
		/*
		for ( int i = 0; i < vWDComp.size(); i++ )
		{
			System.out.println( ( ( WDComp )vWDComp.elementAt( i ) ).toFileWithTab());
		}
		*/

		//	System.out.println( "initClassAttr/Hier/Assoc end! Time: " + ( System.currentTimeMillis() - lStartTime  ) );
	}		//	initClassAttr

	static void initClassAttr1()
	{
		int iAttrID;	//	to store attribute ID
		int iClassID, iChildClassID;	//	to store Father ID
		//	************************
		long lStartTime = System.currentTimeMillis();
		System.out.println( "initClassAttr/Hier/Assoc begin..." );
		
		ClassAttr clattrTemp;
		Vector vQueue;

		vClassAttr = null;
		vClassAttr = new Vector();
		
		vQueue = new Vector();
		vQueue.add( new Integer ( 0 ));
		
		ResultSet rsAttrByClass;
		
		vWDHier = null;
		vWDHier = new Vector();
		
		WDHier wdhTemp;
		
		vWDAssoc = null;
		vWDAssoc = new Vector();
		
		WDAssoc wdaTemp;
		
		do 
		{
			iClassID = Integer.parseInt( vQueue.elementAt( 0 ).toString() );	//	Get father class ID
			try
			{
				pstClassesByClass.setInt( 1, iOntoID );
				pstClassesByClass.setInt( 2, iClassID );
				rsDB = pstClassesByClass.executeQuery();
				if ( rsDB.next() )
				{
					do
					{
						iChildClassID = rsDB.getInt( "ID" );
						vQueue.add( new Integer ( iChildClassID ));
						
						//	Attributes
						pstAttrByClass.setInt( 1, iChildClassID );
						
						boolean bWasFoundAttribute = false;
						
						//	Get new attributes!
						rsAttrByClass = pstAttrByClass.executeQuery();
						if ( rsAttrByClass.next() )
						{
							do
							{
								clattrTemp = null;
								clattrTemp = new ClassAttr( iChildClassID, rsAttrByClass.getInt( "Attr_ID" ), false, iChildClassID );
								vClassAttr.add( clattrTemp );
								if ( !bWasFoundAttribute )
								{
									updateClassAttrPos( iChildClassID, vClassAttr.size() );
									bWasFoundAttribute = true;
								};
								//	System.out.println( clattrTemp.toString() );
							} while( rsAttrByClass.next() );
							
						}	//	get attributes
						
						//	Get inherited  attributes!
						boolean bWasFound = false;
						ClassAttr clattrTemp1;
						for ( int i = 0; i < vClassAttr.size(); i++ )
						{
							clattrTemp1 = ( ClassAttr )vClassAttr.elementAt( i );
							
							if ( clattrTemp1.getClassID() == iClassID )	// found father's attribute
							{
								bWasFound = true;
								clattrTemp = new ClassAttr( iChildClassID, clattrTemp1.getAttrID(), true, clattrTemp1.getFatherClassID() );
								
								vClassAttr.add( clattrTemp );
								if ( !bWasFoundAttribute )
								{
									updateClassAttrPos( iChildClassID, vClassAttr.size() );
									bWasFoundAttribute = true;
								};
							}
							else
							{
								if ( bWasFound )	//	finish a loop
								{
									i = vClassAttr.size() + 1;
								}
							};
						};  			// End of attributes
						
						//	**************************************************************
						
						//	Hierarchy
						pstHierarchy.setInt( 1, iChildClassID );

						bWasFoundAttribute = false;
						
						//	Get new part-of relations!
						rsAttrByClass = pstHierarchy.executeQuery();
						if ( rsAttrByClass.next() )
						{
							do
							{
								wdhTemp = null;
								wdhTemp = new WDHier( iChildClassID, 
										rsAttrByClass.getInt( "Child_class_id" ), false, iChildClassID, 
										rsAttrByClass.getInt( "Card_min" ), 
										rsAttrByClass.getInt( "Card_max" ), 
										rsAttrByClass.getInt( "ID" )
										);
								vWDHier.add( wdhTemp );
							} while( rsAttrByClass.next() );
							
						}	//	get new part-of relations
						
						//	Get inherited  hierarchies!
						bWasFound = false;
						WDHier wdhTemp1;
						for ( int i = 0; i < vWDHier.size(); i++ )
						{
							wdhTemp1 = ( WDHier )vWDHier.elementAt( i );
							
							if ( wdhTemp1.getClass1ID() == iClassID )	// found father's hierarchical relation
							{
								bWasFound = true;
								wdhTemp = new WDHier( iChildClassID, wdhTemp1.getClass2ID(), true, wdhTemp1.getFatherClassID(), wdhTemp1.getCardMin(), wdhTemp1.getCardMax(), wdhTemp1.getIDFromDB() );
								
								vWDHier.add( wdhTemp );
							}
							else
							{
								if ( bWasFound )	//	finish a loop
								{
									i = vWDHier.size() + 1;
								}
							};
						};
						//	End of hierarchy
						
						//	**************************************************************

						//	Associative
						pstAcon.setInt( 1, iChildClassID );

						bWasFoundAttribute = false;
						
						//	Get new associative relations
						rsAttrByClass = pstAcon.executeQuery();
						if ( rsAttrByClass.next() )
						{
							do
							{
								wdaTemp = null;
								wdaTemp = new WDAssoc( iChildClassID, 
										rsAttrByClass.getInt( "Class2_ID" ), 
										false, 
										iChildClassID,
										rsAttrByClass.getInt( "ID" ),
										iCountAssoc++
										 );
								vWDAssoc.add( wdaTemp );
							} while( rsAttrByClass.next() );
							
						}	//	get new associative relations
						
						//	Get inherited  associative relations
						bWasFound = false;
						WDAssoc wdaTemp1;
						for ( int i = 0; i < vWDAssoc.size(); i++ )
						{
							wdaTemp1 = ( WDAssoc )vWDAssoc.elementAt( i );
							
							if ( wdaTemp1.getClass1ID() == iClassID )	// found father's hierarchical relation
							{
								bWasFound = true;
								wdaTemp = new WDAssoc( iChildClassID, 
										wdaTemp1.getClass2ID(), 
										true, 
										wdaTemp1.getFatherClassID(), 
										wdaTemp1.getIDFromDB(),
										iCountAssoc++
										);
								vWDAssoc.add( wdaTemp );
							}
							else
							{
								if ( bWasFound )	//	finish a loop
								{
									i = vWDAssoc.size() + 1;
								}
							};
						};
						//	End of Associative

					} while( rsDB.next() );		//	Loop by subclasses
				}								//	Class has subclasses	
				rsDB = null;
			}
		    catch ( Exception e ) 
		    {
		    	e.printStackTrace( );
		    	return;
		    }
			vQueue.removeElementAt( 0 );
		} while ( vQueue.size() > 0 );

		System.out.println( "initClassAttr/Hier/Assoc end! Time: " + ( System.currentTimeMillis() - lStartTime  ) );
	}		//	initClassAttr1

	static void updateClassAttrPos( int iiClassID, int iiPosClassAttr )
	{
		Classes clTempClass;
		
		if ( ! htClasses.containsKey( new Integer( iiClassID ) ) )
		{
			System.out.println( "Class not found (adding ref to class-attr): " + iiClassID );
			return;
		}
		clTempClass = ( Classes ) htClasses.get( new Integer( iiClassID )  );
		clTempClass.setPosInClassAttr( iiClassID );
		return;
	}

	static void initValuesOfTextAttributes()	//	 ATT! Inherited are not considered.
	{
		WDTextAttrValues wdtavAux;
		byte[] b;
		String sAttrValue, sStemAttrValue;
		
		try
		{
			pstValuesOfTextAttributes.setInt( 1, iOntoID );
			pstValuesOfTextAttributes.setInt( 2, iOntoID );
			pstValuesOfTextAttributes.setInt( 3, iLangID );
			
			rsDB = pstValuesOfTextAttributes.executeQuery();
			if ( rsDB.next() )
			{
				//	System.out.println( "Values of text attributes:" );
				do
				{
                    
					b = null;
					
                    b = rsDB.getBytes("AttrValue");
                    sAttrValue = null == b ? "" : Encodings.bytesTo(b, "UTF8");
                    
                    b = rsDB.getBytes("StemAttrValue");
                    sStemAttrValue = null == b ? "" : Encodings.bytesTo(b, "UTF8");

					wdtavAux = new WDTextAttrValues( rsDB.getInt( "ClassID" ),
							rsDB.getInt( "AttrID" ),
							rsDB.getInt( "ClassAttrID" ),
							sAttrValue, //	rsDB.getString( "AttrValue" ),
							sStemAttrValue, 	//	rsDB.getString( "StemAttrValue" ),
							rsDB.getInt( "ID" )
							);
					vWDTextAttrValues.add( wdtavAux );
					//	System.out.println( wdtavAux.toString() ); 
					
				} while( rsDB.next() );
			}
			else
			{
				//	System.out.println( "Values of text attributes not found" );
			}
			rsDB = null;
		}
	    catch ( Exception e ) 
	    {
	    	e.printStackTrace( );
	    	return;
	    }
	}		//	initValuesOfTextAttributes
}